using UnityEngine;
using System.Collections;

using System;

namespace MyFramework.Runtime.Tool
{
    public class CameraControl : MonoBehaviour
    {
        public enum CameraMode
        {
            Free,
            LookAt,
        }

        public CameraMode cameraMode = CameraMode.Free;

        #region ---------------------------- 自由模式相关 ----------------------------
        /// <summary>
        /// 自由模式：平移的速度 //
        /// </summary>
        public float translationSpeedOfFree = 1.0f;
        /// <summary>
        /// 自由模式：旋转的速度 //
        /// </summary>
        public float rotationSpeedOfFree = 5.0f;
        /// <summary>
        /// 自由模式：拉近、拉远的速度 //
        /// </summary>
        public float zoomSpeedOfFree = 6.0f;

        /// <summary>
        /// 限制旋转X轴的角度范围 //
        /// </summary>
        public float[] limitEulerAnglesXOfFree = new float[] {-360.0f, 360.0f};
        /// <summary>
        /// 限制旋转Y轴的角度范围 //
        /// </summary>
        public float[] limitEulerAnglesYOfFree = new float[] { -89.0f, 89.0f };

        private Vector3 originCameraPositionOfFree;
        private Vector3 originCameraEulerAnglesOfFree;

        private float axisMouseXOfFree;
        private float axisMouseYOfFree;

        private float translationDeltaXOfFree = 0.0f;
        private float translationDeltaYOfFree = 0.0f;
        private float translationDeltaZOfFree = 0.0f;
        private float rotationDeltaXOfFree = 0.0f;
        private float rotationDeltaYOfFree = 0.0f;
        #endregion

        #region ---------------------------- 观察模式相关 ----------------------------
        public Transform transfrom_TargetOfLookAt;
        /// <summary>
        /// 观察模式：X轴旋转的速度 //
        /// </summary>
        public float rotationSpeedXOfLookAt = 250.0f;
        /// <summary>
        /// 观察模式：Y轴旋转的速度 //
        /// </summary>
        public float rotationSpeedYOfLookAt = 120.0f;
        /// <summary>
        /// 观察模式：拉近、拉远的速度 //
        /// </summary>
        public float zoomSpeedOfLookAt = 6.0f;

        public float originDistanceOfLookAt = 6.0f;
        public float originXOfLookAt = 130.0f;
        public float originYOfLookAt = 15.52f;

        /// <summary>
        /// 限制旋转Y轴的角度范围 //
        /// </summary>
        public float[] limitEulerAnglesYOfLookAt = new float[] { 1.0f, 90.0f };
        /// <summary>
        /// 相距目标的距离范围 //
        /// </summary>
        public float[] limitDistanceOfLookAt = new float[] { 1.0f, 30.0f };

        private float axisMouseXOfLookAt;
        private float axisMouseYOfLookAt;

        private float reuseDistanceOfLookAt;
        private Vector3 reuseVector3OfLookAt;
        private Quaternion reuseQuaternionOfLookAt;
        #endregion

        private Camera camera_This;
        private Transform transform_ThisCamera;
        private Ray reuseRay;
        private RaycastHit reuseRaycastHit;

        void Awake()
        {
            camera_This = this.GetComponent<Camera>();
            transform_ThisCamera = camera_This.transform;
            originCameraPositionOfFree = transform_ThisCamera.position;
            originCameraEulerAnglesOfFree = transform_ThisCamera.eulerAngles;
        }

        void LateUpdate()
        {
            // 重置 //
            if(Input.GetKeyUp(KeyCode.Space))
            {
                if(cameraMode == CameraMode.Free)
                {
                    ResetFreeMode();
                }
                else if(cameraMode == CameraMode.LookAt)
                {
                    ResetLookAtMode();
                }
            }

            if(Input.GetKeyUp(KeyCode.F))
            {
                cameraMode = CameraMode.Free;
                ResetFreeMode();
            }

            if(Input.GetKeyUp(KeyCode.L))
            {
                cameraMode = CameraMode.LookAt;
                ResetLookAtMode();
            }

            if(cameraMode == CameraMode.Free)
            {
                OnFreeMode();
            }
            else if(cameraMode == CameraMode.LookAt)
            {
                OnLookAtMode();
            }
        }

        #region ---------------------------- 自由模式相关 ----------------------------
        /// <summary>
        /// 重置自由模式 //
        /// </summary>
        void ResetFreeMode()
        {
            transform_ThisCamera.position = originCameraPositionOfFree;
            transform_ThisCamera.eulerAngles = originCameraEulerAnglesOfFree;
        }

        void OnFreeMode()
        {
            if(Input.GetMouseButton(1))
            {
                rotationDeltaXOfFree += Input.GetAxis("Mouse X") * rotationSpeedOfFree;
                rotationDeltaYOfFree -= Input.GetAxis("Mouse Y") * rotationSpeedOfFree;
                rotationDeltaXOfFree = ClampAngle(rotationDeltaXOfFree, limitEulerAnglesXOfFree[0], limitEulerAnglesXOfFree[1]);
                rotationDeltaYOfFree = ClampAngle(rotationDeltaYOfFree, limitEulerAnglesYOfFree[0], limitEulerAnglesYOfFree[1]);
                transform_ThisCamera.rotation = Quaternion.Euler(rotationDeltaYOfFree, rotationDeltaXOfFree, 0);
            }

            if(Input.GetMouseButton(2))
            {
                axisMouseXOfFree = Input.GetAxis("Mouse X");
                if(Mathf.Abs(axisMouseXOfFree - 0.1f) > 0.0f)
                {
                    translationDeltaXOfFree = axisMouseXOfFree * translationSpeedOfFree;
                    transform_ThisCamera.position = transform_ThisCamera.position + transform_ThisCamera.right * translationDeltaXOfFree * -1;
                }

                axisMouseYOfFree = Input.GetAxis("Mouse Y");
                if(Mathf.Abs(axisMouseYOfFree - 0.1f) > 0.0f)
                {
                    translationDeltaYOfFree = axisMouseYOfFree * translationSpeedOfFree;
                    transform_ThisCamera.position = transform_ThisCamera.position + transform_ThisCamera.up * translationDeltaYOfFree * -1;
                }
            }

            if(Input.GetAxis("Mouse ScrollWheel") != 0)
            {
                translationDeltaZOfFree = Input.GetAxis("Mouse ScrollWheel") * zoomSpeedOfFree;
                transform_ThisCamera.position = transform_ThisCamera.position + transform_ThisCamera.forward * translationDeltaZOfFree;
            }
        }
        #endregion

        #region ---------------------------- 观察模式相关 ----------------------------
        /// <summary>
        /// 重置自由模式 //
        /// </summary>
        void ResetLookAtMode()
        {
            if(transfrom_TargetOfLookAt == null)
            {
                return;
            }

            transform.rotation = Quaternion.Euler(originYOfLookAt, originXOfLookAt, 0f);
            transform.position = Quaternion.Euler(originYOfLookAt, originXOfLookAt, 0f) * new Vector3(0.0f, 0.0f, -originDistanceOfLookAt) + transfrom_TargetOfLookAt.position;
        }

        void OnLookAtMode()
        {
            if(Input.GetMouseButtonUp(0))
            {
                reuseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
                if(Physics.Raycast(reuseRay, out reuseRaycastHit))
                {
                    transfrom_TargetOfLookAt = reuseRaycastHit.transform;
                }
            }

            if(transfrom_TargetOfLookAt == null)
            {
                return;
            }

            if(Input.GetMouseButton(1) || Input.GetAxis("Mouse ScrollWheel") != 0)
            {
                reuseDistanceOfLookAt = Vector3.Distance(transfrom_TargetOfLookAt.position, transform_ThisCamera.position);
                axisMouseXOfLookAt += Input.GetAxis("Mouse X") * rotationSpeedXOfLookAt * 0.02f;
                axisMouseYOfLookAt -= Input.GetAxis("Mouse Y") * rotationSpeedYOfLookAt * 0.02f;
                axisMouseYOfLookAt = ClampAngle(axisMouseYOfLookAt, limitEulerAnglesYOfLookAt[0], limitEulerAnglesYOfLookAt[1]);

                reuseDistanceOfLookAt -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeedOfLookAt;
                reuseDistanceOfLookAt = Mathf.Clamp(reuseDistanceOfLookAt, limitDistanceOfLookAt[0], limitDistanceOfLookAt[1]);

                reuseQuaternionOfLookAt = Quaternion.Euler(axisMouseYOfLookAt, axisMouseXOfLookAt, 0f);
                reuseVector3OfLookAt = Quaternion.Euler(axisMouseYOfLookAt, axisMouseXOfLookAt, 0f) * new Vector3(0.0f, 0.0f, -reuseDistanceOfLookAt) + transfrom_TargetOfLookAt.position;

                transform.rotation = reuseQuaternionOfLookAt;
                transform.position = reuseVector3OfLookAt;
            }
        }
        #endregion

        private float ClampAngle(float angle, float minAngle, float maxAgnle)
        {
            if(angle <= -360)
                angle += 360;
            if(angle >= 360)
                angle -= 360;

            return Mathf.Clamp(angle, minAngle, maxAgnle);
        }
    }
}